3

简介:本篇是记录搭建流程,不过多叙述,搭建的细节,主要以前端为主,项目是主要是为了重构前端代码,后端代码完全复用,还会有篇主要讲node项目的搭建

项目背景:

一个客服项目,原来是react+express实现,现在改为vue+express实现

开发环境前后端同时实现热加载

实现:webpack配置,分开发环境与线上环境:
开发环境前端使用wbepack-dev-server来进行热更新和加载,后端使用nodemon来实现
线上环境使用build出的dist目录挂载到express static上来实现

三种实现方式:
旧版本:在开发时,同时起两个服务webpack-dev-server和api的node-server,使用node-server代理前端页面
新版本:webpack升级webpack-hot-middleware的出现,开发时,使用webpack-hot-middleware在node-server的基础上进行拓展处理
我的另一个想法:也是同时起两个服务webpack-dev-server和api的node-server,使用dev-server来代理node-server的接口,因为vue-cli3没有暴露出webpack的配置文件,在vue-config.js中可配置dev-server的proxy

如果想看前两种具体实现,我会写的,不过是之后占坑~

旧版本实现

// npm script
"start": "node ./node_modules/concurrently/src/main.js --kill-others \"npm run watch-client\" \"npm run dev-server\"",
"watch-client": "node ./webpack/webpack-dev-server.js ",
"dev-server": "nodemon ./app.js | bunyan",

// node-server代理前端路径
router.use('/', fetchUserInfo, async (req, res) => {
  try {
    if (__DEVELOPMENT__) {
      const result = await request.get('http://localhost:8027/view/index.html')
      res.send(result.text)
      return res.end()
    } else {
      res.sendFile('/', {
        root: `${process.cwd()}`,
      }, (err) => {
        if (err) {
          logger.error(`error whild send file, err is : ${err}`)
          res.status(err.status).end()
        }
      })
      return
    }
  } catch (e) {
    logger.error('error in feedback router', e)
  }
})

新版本实现

// npm script
"start": "nodemon index.js | bunyan", // 在index.js中判断

// 使用middleware处理代码。这里不展开讲dev-hot,详情请见我的另一篇blog
if (config.useHotServer) {
  require('./dev-hot').default(app)
} else {
  app.use(
    history({ index: `/index-v${appPackage.version}.html` }),
    express.static(config.buildStaticDir),
  )
}

基于vue-cli3我的实现

//npm script
"serve": "vue-cli-service serve"
"dev-server": "nodemon ./app.js | bunyan"
"start": "node ./node_modules/concurrently/src/main.js --kill-others \"npm run serve\" \"npm run dev-server\"",

//vue.config.js
module.exports = {
  devServer: {
    proxy: 'http://10.1.100.189:8025',
  },
}

部署问题:vue-router不能直接使用express.static

vue到react,node/express挂载vue-router不能直接使用express.static
vue-router history模式与express connect-history-api-fallback中间件搭配使用

connect-history-api-fallback是什么:

能够代理请求返回一个指定的页面的中间件

解决什么场景下的问题:

在express的静态文件夹设置为dist目录的时候,出现各种404错误,经过查询,发现当路由模式为history的时候,后端会直接请求地址栏中的文件,这样就会出现找不到的情况,需要结合express的connect-history-api-fallback来处理。

思路:

当请求满足以下条件的时候,该库会把请求地址转到默认(默认情况为index.html)

1.请求方式为GET(前端路由请求的当然要是GET)
2.接受文件类型为text/html(即ajax请求中的dataType)
3.与options.rewrites中提供的模式不匹配(即自定义规则中没写到的)

基础api:

index:配置默认的index页面
rewrites:通过正则配置,配置相关路由
verbose:日志选项
htmlAcceptHeaders:覆盖Accepts,更改请求的dataType配置
disableDotRule

demo:

import history from 'connect-history-api-fallback'
// 需要在express.static上面
app.use(history())
app.use(express.static(path.join(__dirname, '../dist')))

vue-cli3中引入sass

直接安装sass-loader,vue-cli3可以自动识别支持

封装axios请求(代码更易读/错误处理)

使用:
await request.get('/api/current')
await request.post('/api/message', { messageInfo })

utils/request.js

import axios from 'axios'

async function requestService(url, method = 'GET', params = {}, headers = {}) {
  let ret = {}
  try {
    let query = {}
    let body = {}
    const customHeaders = headers // 这里可以扩展headers
    if (method === 'GET') {
      query = params
    } else {
      body = params
    }
    const res = await axios({
      url,
      method,
      params: query,
      data: body,
      headers: customHeaders,
    })
    ret = res.data
  } catch (err) {
    console.error(`Request ${url} Error `, err.stack)
    throw new Error(JSON.stringify(err.response.data))
  }
  return ret
}

function request(url, params = {}, headers = {}) {
  return requestService(url, 'GET', params, headers)
}

request.get = (url, params = {}, headers = {}) => requestService(url, 'GET', params, headers)
request.del = (url, params = {}, headers = {}) => requestService(url, 'DELETE', params, headers)
request.post = (url, params = {}, headers = {}) => requestService(url, 'POST', params, headers)
request.put = (url, params = {}, headers = {}) => requestService(url, 'PUT', params, headers)
request.patch = (url, params = {}, headers = {}) => requestService(url, 'PATCH', params, headers)

export default request

引入神策数据埋点

具体看另一篇blog,讲述了在项目中遇到的在react/vue/node项目中引入神策数据埋点

引入bridge

utils/
该项目需要调起相册,相机等功能,需要与native交互,具体看另一篇blog(ps:可能还没写,我先占个坑~)

引入常用的工具方法 Utils

请求 - request.js
时间格式校验 - formatDate.js - 原来使用moment.js,but库太大了
cookie获取 - getCookie
etc...
具体看另一篇blog(占坑)

未完待续...


Rainie
441 声望36 粉丝

全栈攻城狮